using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using AForge.Imaging.Filters;
using System.Drawing.Imaging;

namespace PBR.Filters
{
    public class AlphaMatte
    {
        public void ApplyInPlace(Bitmap matteImage, Bitmap toMatteImage)
        {
            if (matteImage.PixelFormat != PixelFormat.Format32bppArgb || toMatteImage.PixelFormat != PixelFormat.Format32bppArgb)
            {
                throw new ArgumentException("AlphaMatte Apply takes two 32 bit images");
            }
            if (matteImage.Width != toMatteImage.Width || matteImage.Height != toMatteImage.Height)
            {
                throw new ArgumentException("AlphaMatte Apply takes 2 same size images");
            }
            
            BitmapData matteData = matteImage.LockBits(
                new Rectangle(0, 0, matteImage.Width, matteImage.Height),
                ImageLockMode.ReadOnly, matteImage.PixelFormat);

            BitmapData toMatteData = toMatteImage.LockBits(
                new Rectangle(0, 0, toMatteImage.Width, toMatteImage.Height),
                ImageLockMode.ReadWrite, toMatteImage.PixelFormat);

            // process the filter
            ProcessFilter(matteData, toMatteData);

            // unlock destination images
            matteImage.UnlockBits(matteData);
            toMatteImage.UnlockBits(toMatteData);

            return;
        }

        private unsafe void ProcessFilter(BitmapData matteData, BitmapData toMatteData)
        {
			// get width and height
            int width = matteData.Width;
            int height = matteData.Height;

            int offset = matteData.Stride - width * 4;

			// do the job
			byte* mattePtr = (byte *) matteData.Scan0.ToPointer();
            byte* toMattePtr = (byte*) toMatteData.Scan0.ToPointer();

			// for each line
			for ( int y = 0; y < height; y++ )
			{
				// for each pixel
                for (int x = 0; x < width; x++, mattePtr += 4, toMattePtr += 4)
				{
                    toMattePtr[AForge.Imaging.RGBA.A] = (byte)((toMattePtr[AForge.Imaging.RGBA.A] * mattePtr[AForge.Imaging.RGBA.A]) / 255);
				}
                mattePtr += offset;
                toMattePtr += offset;
			}
		}
    }
}

